#include "ConfigManager.h"

bool ConfigManager::LoadGameConfig(const std::string &path)
{
    std::ifstream file(path);
    if (!file.good()) {
        return false;
    }
    std::stringstream sinStr;
    sinStr << file.rdbuf();
    file.close();
    json root = json::parse(sinStr.str());
    if (root.empty()) {
        return false;
    }
    LoadGameConfigBasic(root);
    LoadGameConfigPlayer(root);
    LoadGameConfigTower(root);
    LoadGameConfigEnemy(root);
    return true;
}

bool ConfigManager::LoadLevelConfig(const std::string& path)
{
    std::ifstream file(path);
    if (!file.good()) {
        return false;
    }
    std::stringstream sinStr;
    sinStr << file.rdbuf();
    file.close();
    json root = json::parse(sinStr.str());
    if (root.empty()) {
        return false;
    }
    std::unordered_map<std::string, EnemyType> nameMap = {
            {"Slim", EnemyType::Slim},
            {"KingSlim", EnemyType::Slim},
            {"Skeleton", EnemyType::Slim},
            {"Goblin", EnemyType::Slim},
            {"GoblinPriest", EnemyType::Slim}
    };
    for (const auto &waveJson: root) {
        Wave wave;
        wave.interval = waveJson["interval"];
        wave.rewards = waveJson["rewards"];
        for (auto &spawnJson: waveJson["spawn_list"]) {
            Wave::SpawnEvent spawnEvent;
            spawnEvent.interval = spawnJson["interval"];
            spawnEvent.point = spawnJson["point"];
            spawnEvent.enemyType = nameMap[spawnJson["enemy"]];
            wave.spawn_event_list.push_back(spawnEvent);
        }
        waveList.push_back(wave);
    }
    return true;
}

void ConfigManager::LoadGameConfigBasic(json &root)
{
    json node = root["basic"];
    basic_template.window_title = node["window_title"];
    basic_template.window_height = node["window_height"];
    basic_template.window_width = node["window_width"];
}

void ConfigManager::LoadGameConfigPlayer(json &root)
{
    json node = root["player"];
    player_template.speed = node["speed"];
    player_template.normal_attack_interval = node["normal_attack_interval"];
    player_template.normal_attack_damage = node["normal_attack_damage"];
    player_template.skill_interval = node["skill_interval"];
    player_template.skill_damage = node["skill_damage"];
}

void ConfigManager::LoadGameConfigTower(json &root)
{
    json tower = root["tower"];
    LoadGameConfigTowerOne(tower["archer"], archer_template);
    LoadGameConfigTowerOne(tower["axeman"], axeman_template);
    LoadGameConfigTowerOne(tower["gunner"], gunner_template);
}

void ConfigManager::LoadGameConfigTowerOne(json &node, TowerTemplate &towerTemplate)
{
    ParseJsonArray(towerTemplate.interval, node["interval"]);
    ParseJsonArray(towerTemplate.damage, node["damage"]);
    ParseJsonArray(towerTemplate.view_range, node["view_range"]);
    ParseJsonArray(towerTemplate.cost, node["cost"]);
    ParseJsonArray(towerTemplate.upgrade_cost, node["upgrade_cost"]);
}

void ConfigManager::LoadGameConfigEnemy(json &root)
{
    json enemy = root["enemy"];
    LoadGameConfigEnemyOne(enemy["slim"], slim_template);
    LoadGameConfigEnemyOne(enemy["king_slim"], king_slim_template);
    LoadGameConfigEnemyOne(enemy["skeleton"], skeleton_template);
    LoadGameConfigEnemyOne(enemy["goblin"], goblin_template);
    LoadGameConfigEnemyOne(enemy["goblin_priest"], goblin_priest_template);
}

void ConfigManager::LoadGameConfigEnemyOne(json &node, EnemyTemplate &enemyTemplate)
{
    enemyTemplate.hp = node["hp"];
    enemyTemplate.speed = node["speed"];
    enemyTemplate.damage = node["damage"];
    enemyTemplate.reward_ratio = node["reward_ratio"];
    enemyTemplate.recover_interval = node["recover_interval"];
    enemyTemplate.recover_range = node["recover_range"];
    enemyTemplate.recover_intensity = node["recover_intensity"];
}

void ConfigManager::ParseJsonArray(std::vector<double> &vec, json &arrJson)
{
    for (auto &a: arrJson) {
        vec.push_back(a);
    }
}